package org.jiuling.baidu.nlp;

import com.baidu.aip.nlp.AipNlp;
import org.jiuling.baidu.nlp.config.BaiDuNlpConfig;
import org.jiuling.baidu.nlp.enums.QPSEnum;
import org.jiuling.baidu.nlp.enums.UseTypeEnum;
import org.jiuling.baidu.nlp.model.AddressModel;
import org.jiuling.basics.converter.StringConvert;
import org.jiuling.basics.validation.IntegerVerify;
import org.jiuling.cache.Cache;
import org.jiuling.cache.impl.SimpleCache;
import org.json.JSONObject;

import java.util.HashMap;

/**
 * 地址识别
 * @author 紫灵
 * @date 2024年08月18日 14时40分27秒
 */
public class AddressRecognition {


    /** 超时时间 */
    private final int timeOut = 1000;
    /** 并发 */
    private final int qps;
    /** 百度自然语言识别配置 */
    private final BaiDuNlpConfig baiDuNlpConfig;
    /** aip自然语言识别 */
    private final AipNlp aipNlp;
    /** 缓存 */
    private static final Cache<String,Integer> cache =  new SimpleCache<>();

    public AddressRecognition(BaiDuNlpConfig baiDuNlpConfig) {
        this.baiDuNlpConfig = baiDuNlpConfig;
        switch (baiDuNlpConfig.getUseType()){
            case PAYMENT:
                this.qps = QPSEnum.ADDRESS_RECOGNITION.getPayment();
                break;
            case PERSONAL:
                this.qps = QPSEnum.ADDRESS_RECOGNITION.getPersonal();
                break;
            default:
                // 默认使用个人，以达到最低限度使用
                this.qps = QPSEnum.ADDRESS_RECOGNITION.getCompany();
        }
        this.aipNlp =  new AipNlp(baiDuNlpConfig.getAppId(), baiDuNlpConfig.getApiKey(), baiDuNlpConfig.getSecretKey());
    }

    /** 重试次数 */
    private int retryCount = 0;
    /**
     * 识别
     * @param address 地址
     */
    public AddressModel identify(String address){
        this.qpsLimitation();
        // 传入可选参数调用接口
        HashMap<String, Object> options = new HashMap<String, Object>();
        // 获取到json地址
        JSONObject jsonAddress = aipNlp.address(address, options);

        if (!jsonAddress.isNull("error_code")){
            if (jsonAddress.getInt("error_code") == 18 ){
                // 将剩余时间暂停
                try {
                    Thread.sleep(cache.getRemainder(this.baiDuNlpConfig.getApiKey()));
                } catch (InterruptedException ignored) {
                }
                // 限制重试次数
                if (retryCount <= 6){
                    retryCount ++;
                    return this.identify(address);
                }
            }
            retryCount = 0;
            throw new RuntimeException(jsonAddress.getString("error_msg"));
        }
        return AddressModel.builder()
                .addLogId(jsonAddress.getLong("log_id"))
                .addText(jsonAddress.getString("text"))
                .addProvince(jsonAddress.getString("province"))
                .addProvinceCode(jsonAddress.getString("province_code"))
                .addCity(jsonAddress.getString("city"))
                .addCityCode(jsonAddress.getString("city_code"))
                .addCounty(jsonAddress.getString("county"))
                .addCountyCode(jsonAddress.getString("county_code"))
                .addTown(jsonAddress.getString("town"))
                .addTownCode(jsonAddress.getString("town_code"))
                .addPerson(jsonAddress.getString("person"))
                .addDetail(jsonAddress.getString("detail"))
                .addPhonenum(jsonAddress.getString("phonenum"))
                .addLat(jsonAddress.getDouble("lat"))
                .addLng(jsonAddress.getDouble("lng"))
                .build();
    }

    /**
     * QPS限制
     */
    private void qpsLimitation(){
        // 获取到缓存作为key
        String key = this.baiDuNlpConfig.getApiKey();
        // 获取到当前QPS
        Integer currentQps = cache.get(key);
        // 如果当前缓存为空则设置缓存
        if (IntegerVerify.isBlank(currentQps)){
            cache.put(key,1,this.timeOut);
        }else {
            // 判断当前缓存是否大于或者等于历史缓存
            if (currentQps >= this.qps){
                // 将剩余时间暂停
                try {
                    Thread.sleep(cache.getRemainder(key));
                } catch (InterruptedException ignored) {
                }
                // 重新校验一次限制
                this.qpsLimitation();
            }else {
                cache.updateValue(key,currentQps+1);
            }
        }
    }

    public static void main(String[] args) {
        BaiDuNlpConfig baiDuNlpConfig = BaiDuNlpConfig.builder()
                .addAppId("115588845")
                .addApiKey("p4Zy8tZoMLaRAPwvFesOzKJi")
                .addSecretKey("GSH1fK38JbSDdK9oViBgTshDevV9iJ4W")
                .addUseType(UseTypeEnum.PERSONAL)
                .build();
        AddressRecognition addressRecognition = new AddressRecognition(baiDuNlpConfig);
        String addr = "成都市高新区和平路戛纳湾滨江3号";
        AddressModel addressModel = addressRecognition.identify(addr);
        System.out.println(addressModel.toString());
//        System.out.println(StringConvert.format("地址：{},坐标：{},{}","{}",addr,addressModel.getLng(),addressModel.getLat()));
//        String[] addrs = {"高新区中和大道一段天益花园小区附近工地","高新区雅和北五路工地","高新区雅和北二路与锦龙街交叉口附近","高新区南华路与天府四街交叉口","高新区观东二街","高新区世纪城南路410号","高新区天华路英郡小区","高新区东寺街和东寺南一路路口","高新区新川路创智广场","高新区吉瑞一路","高新区观东二街","高新区龙灯山路","高新区天府二街","高新区锦蜀街","高新区天府二街凤凰城旁边的公园","高新区德华路","高新区天府二街伊藤洋华堂","高新区锦蜀街","高新区天府五街观音湾路","高新区悦和二街的几家烧烤店","高新区梓州大道怡馨家园","高新区梓州大道与锦韵路6号交叉口","高新区雅和南四路","高新区应龙北一路96好3栋1403","高新区新川路创智广场","高新区东寺街与东寺南一路路口","高新区观东一街","高新区盛邦街","高新区和乐三街","高新区和乐三街","高新区观东二街","高新区盛治街","高新区盛治街890号荟优选","高新区雅和南四路七里社区旁边的露天篮球场内","高新区锦龙街","高新区雅和南四路七里社区旁边的露天篮球场内","高新区新川路","高新区和乐三街","高新区观东二街","高新区雅和南四路七里社区旁边的露天篮球场内","高新区盛邦街","高新区和乐三街","高新区盛治街890号荟优选","高新区雅和南四路七里社区旁边的露天篮球场内","高新区盛治街","高新区锦龙街","高新区吉瑞五路和吉庆二路交叉口的自行车店","高新区和乐三街","高新区观东二街","高新区天府三街","高新区天府二街大源南二街廖记棒棒鸡对面","高新区观东三街","高新区吉庆四路保利楼盘项目","高新区观东二街","高新区盛邦街","高新区天府四街"};
//        for (String address : addrs){
//            AddressModel addressModel = addressRecognition.identify("成都"+address);
//            System.out.println(StringConvert.format("地址：{},坐标：{},{}","{}",address,addressModel.getLng(),addressModel.getLat()));
//        }
    }
}
